package com.songxh.application.impl;

import com.songxh.application.api.BlogDetailsService;
import com.songxh.application.dto.details.*;
import com.songxh.core.base.CommonResult;
import com.songxh.core.entity.UserContext;
import com.songxh.core.utils.DateUtils;
import com.songxh.core.utils.LoginUtils;
import com.songxh.domain.service.api.*;
import com.songxh.domain.service.report.ReportUtils;
import com.songxh.infrastructure.db.mapper.ArticleMapper;
import com.songxh.infrastructure.db.mapper.SysUserMapper;
import com.songxh.infrastructure.db.mapper.TagMapper;
import com.songxh.infrastructure.db.pojo.*;
import jdk.nashorn.internal.ir.ReturnNode;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 博客详情接口
 *
 * @author songxh
 * @create 2022-12-20-15:53
 */
@Service
public class BlogDetailsServiceImpl implements BlogDetailsService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private ArticleService articleService;

    @Autowired
    private ArticleBodyService articleBodyService;

    @Autowired
    private ReportUtils reportUtils;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private CommentService commentService;

    @Autowired
    private TagMapper tagMapper;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private ArticleTagRelService articleTagRelService;

    @Autowired
    private LikeService likeService;

    /**
     * 文章详情，同时异步更新浏览数量
     *
     * @param detailsParamsDTO
     * @return
     */
    @Override
    public CommonResult<DetailsResultDTO> showDetails(DetailsParamsDTO detailsParamsDTO) {
        DetailsResultDTO detailsResultDTO = new DetailsResultDTO();

        //获取品类详情
        List<CategorySummaryDTO> categorySummary = articleMapper.getCategorySummary(detailsParamsDTO.getAuthorId());
        detailsResultDTO.setCategorySummaryDTOList(categorySummary);

        //获取时间段文章数据
        List<TimeSummaryDTO> timeSummary = articleMapper.getTimeSummary(detailsParamsDTO.getAuthorId());
        detailsResultDTO.setTimeSummaryDTOList(timeSummary);

        //获取文章基础信息
        Article article = articleService.lambdaQuery()
                .eq(Article::getId, detailsParamsDTO.getArticleId())
                .one();
        detailsResultDTO.setArticle(article);

        //获取文章内容数据
        ArticleBody articleBody = articleBodyService.lambdaQuery()
                .eq(ArticleBody::getArticleId, detailsParamsDTO.getArticleId())
                .one();
        detailsResultDTO.setArticleBody(articleBody);

        //获取用户信息
        SysUser author = sysUserMapper.getUserById(detailsParamsDTO.getArticleId());
        detailsResultDTO.setSysUser(author);

        //更新浏览数量
        reportUtils.handlerViewCountAsync(article, articleService);

        return CommonResult.success(detailsResultDTO);
    }


    /**
     * 获取评论详情
     *
     * @param articleId 文章id
     * @return
     */
    @Override
    public List<CommentResultDTO> getComments(Long articleId) {
        //获取用户id
        UserContext userContext = LoginUtils.get();
        Long userId = userContext.getId();

        List<CommentResultDTO> resultDTOS = new ArrayList<>();
        //1、根据文章id查询评论
        List<Comment> oneCommentList = commentService.lambdaQuery()
                .eq(Comment::getArticleId, articleId)
                .eq(Comment::getIsDeleted, 0)
                .orderByDesc(Comment::getcT) //根据创建时间倒叙排列，从而最顶端显示最新评论
                .list();
        //第一层级较特殊，对一级评论进行单独处理
        Integer one = 1;
        List<Comment> collect = oneCommentList.stream().filter(e -> one.equals(e.getLevel())).collect(Collectors.toList());
        for (Comment comment : collect) {
            CommentResultDTO resultDTO = new CommentResultDTO();
            resultDTO.setCommentId(comment.getId());
            resultDTO.setContent(comment.getContent());
            resultDTO.setCreatData(DateUtils.format(comment.getcT(), DateUtils.DEFAULT_DATE_TIME_FORMAT));
            resultDTO.setLevel(one);
            //2、根据作者id查询作者信息
            SysUser author = sysUserMapper.getUserById(comment.getCurrentUid());
            UserDTO userDTO = new UserDTO();
            BeanUtils.copyProperties(author, userDTO);
            resultDTO.setUserDTO(userDTO);
            //3、获取子评论，类似DFS
            List<CommentResultDTO> children = getChildren(one + 1, comment.getId(), oneCommentList, userDTO, userId, articleId);
            resultDTO.setChildren(children);

            //点赞验证
            boolean likeMes = getLikeMes(userId, articleId, comment.getId());
            if (likeMes){
                resultDTO.setLiked("1");
            }else {
                resultDTO.setLiked("0");
            }

            resultDTOS.add(resultDTO);
        }

        return resultDTOS;
    }

    /**
     * 评论
     * @param commentParamsDTO
     * @return
     */
    @Override
    public CommonResult comment(CommentParamsDTO commentParamsDTO) {
        //获取当前用户信息
        UserContext userContext = LoginUtils.get();
        Comment comment = new Comment();
        comment.setCurrentUid(userContext.getId());
        comment.setArticleId(commentParamsDTO.getArticleId());
        comment.setContent(commentParamsDTO.getContent());
        comment.setParentId(commentParamsDTO.getParent());
        comment.setToUid(commentParamsDTO.getToUserId());

        //设置评论登记，获取上级评论
        if (commentParamsDTO.getParent() != 0){//等于0即为一级评论
            Comment commentServiceById = commentService.getById(commentParamsDTO.getParent());
            comment.setLevel(commentServiceById.getLevel() + 1);
        }else {
            comment.setLevel(0);
        }

        commentService.save(comment);
        return CommonResult.success();
    }

    /**
     * 获取所有tag
     * @return
     */
    @Override
    public List<TagResultDTO> getTags() {
        List<TagResultDTO> tags = tagMapper.getTags();
        return tags;
    }

    /**
     * 获取所有的品类，类似评论 有层级
     * @return
     */
    @Override
    public List<CategoryResultDTO> getCategory() {
        List<Category> categories = categoryService.lambdaQuery().eq(Category::getIsDeleted, 0).list();
        List<CategoryResultDTO> categoryResultDTOS = getCategoryChildren(1, (long) 0, categories);
        return categoryResultDTOS;
    }

    /**
     * 保存文章
     * @param articleParamDTO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult save(InsertArticleParamDTO articleParamDTO) {
        //1. 发布文章 目的 构建Article对象
        Article article = new Article();
        //2. 作者id  当前的登录用户
        UserContext userContext = LoginUtils.get();
        article.setAuthorId(userContext.getId());
        article.setCategoryId(articleParamDTO.getCategorySingleDto().getCategoryId());
        article.setSummary(articleParamDTO.getSummary());
        article.setTitle(articleParamDTO.getTitle());
        article.setViewCounts(0);
        article.setWeight(Article.Article_Common);
        article.setCommentCounts(0);
        article.setBodyId(-1l);
        articleService.save(article);
        //3. 标签  要将标签加入到 关联列表当中
        List<TagResultDTO> tags = articleParamDTO.getTags();
        for (TagResultDTO tag : tags) {
            ArticleTagRel articleTagRel = new ArticleTagRel();
            articleTagRel.setArticleId(article.getId());
            articleTagRel.setTagId(tag.getTagId());
            //保存文章标签关联
            articleTagRelService.save(articleTagRel);
        }
        //4. body 内容存储 article bodyId
        ArticleBody articleBody = new ArticleBody();
        articleBody.setArticleId(article.getId());
        articleBody.setContent(articleParamDTO.getArticleContentDTO().getContent());
        articleBody.setContentHtml(articleParamDTO.getArticleContentDTO().getContentHtml());
        articleBodyService.save(articleBody);

        //修改文章表中文章详情id
        article.setBodyId(articleBody.getId());
        articleService.updateById(article);

        return CommonResult.success();
    }

    /**
     * 递归遍历所有的品类
     * @param level 层级
     * @param parentId  父品类id
     * @param categories  所有品类
     * @return
     */
    private List<CategoryResultDTO> getCategoryChildren(Integer level, Long parentId, List<Category> categories){
        List<CategoryResultDTO> categoryResultDTOS = new ArrayList<>();
        //结束条件
        List<Category> collect = categories.stream().filter(e -> level.equals(e.getLevel()) && parentId.equals(e.getParentId())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect)){
            return null;
        }

        for (Category category : collect) {
            CategoryResultDTO resultDTO = new CategoryResultDTO();
            resultDTO.setCategoryId(category.getId());
            resultDTO.setCategoryName(category.getCategoryName());
            resultDTO.setCategoryCode(category.getCategoryCode());
            //递归
            List<CategoryResultDTO> children = getCategoryChildren(level + 1, category.getId(), categories);
            resultDTO.setChildrens(children);
            categoryResultDTOS.add(resultDTO);
        }
        return categoryResultDTOS;
    }

    /**
     * 获取子评论
     *
     * @param level    层级
     * @param ParentId 父评论id
     * @param comments 该文章所以的评论
     * @param toUser   上级评论的用户信息
     * @return
     */
    private List<CommentResultDTO> getChildren(Integer level, Long ParentId, List<Comment> comments, UserDTO toUser, Long userId, Long articleId) {
        List<CommentResultDTO> list = new ArrayList<>();
        //设置退出条件，当该层级且该父id为筛选条件时，没有数据，便结束
        List<Comment> collect = comments.stream().filter(e -> ParentId.equals(e.getParentId()) && level.equals(e.getLevel())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(collect)) {
            return null;
        }
        //对该层级该父id所以的评论进行处理
        for (Comment comment : collect) {
            CommentResultDTO resultDTO = new CommentResultDTO();
            resultDTO.setCommentId(comment.getId());
            resultDTO.setContent(comment.getContent());
            resultDTO.setCreatData(DateUtils.format(comment.getcT(), DateUtils.DEFAULT_DATE_TIME_FORMAT));
            resultDTO.setLevel(level);
            //根据作者id查询作者信息
            SysUser author = sysUserMapper.getUserById(comment.getCurrentUid());
            UserDTO userDTO = new UserDTO();
            BeanUtils.copyProperties(author, userDTO);
            resultDTO.setUserDTO(userDTO);
            //递归获取字评论
            List<CommentResultDTO> children = getChildren(level + 1, comment.getId(), comments, userDTO, userId, articleId);
            resultDTO.setChildren(children);
            resultDTO.setToUser(toUser);//设置上层评论用户数据
            //点赞验证
            boolean likeMes = getLikeMes(userId, articleId, comment.getId());
            if (likeMes){
                resultDTO.setLiked("1");
            }else {
                resultDTO.setLiked("0");
            }

            list.add(resultDTO);
        }
        return list;
    }

    /**
     * 查看该评论是否被点赞
     * @param userId
     * @param articleId
     * @param commentId
     */
    private boolean getLikeMes(Long userId, Long articleId, Long commentId){
        //获取点赞情况
        List<Like> likes = likeService.lambdaQuery()
                .eq(Like::getArticleId, articleId)
                .eq(Like::getUserId, userId)
                .eq(Like::getCommentId, commentId)//如果是给文章点赞，那么表中的评论id为默认值 0
                .list();
        if (CollectionUtils.isNotEmpty(likes)){
            //已点赞
            return true;
        }else {
            return false;
        }
    }

}
